<?php
include_once './config.php';
include_once './Location.php';

/**
 * This class represents a Facebook user - the logged in user
 * and also his/her friends using this application.
 * 
 * TODO set the instance fields access to private
 */
class User {

	///////////////////////////////////////////////////////////////////////////
	// Instance fields
	//

	/**
	 * The Facebook uid of the user
	 */
	public $fb_uid;

	/**
	 * The Facebook user name (full name)
	 */
	public $fb_name;

	/**
	 * URL to the user profile photo
	 */
	public $fb_pic_url;

	/**
	 * array of friends (each element is type of User)
	 * @var array
	 */
	public $fb_friends;

	/**
	 * The position of the user
	 * @var Location
	 */
	public $fb_location;
	
	/**
	 * This associative array can hold some unusual FB data, like bigger/smaller profile photo, etc.
	 * The key must be the column name in the FB user table, the value is the column value from the user FB table.
	 * @var array
	 */
	public $fb_extra_data = array();

	///////////////////////////////////////////////////////////////////////////
	// Constructor
	//

	/**
	 * Creates a new User object.
	 *
	 * @param $uid FB user id
	 * @param $name full name
	 * @param $pic_url url to the profile photo
	 * @throws InvalidArgumentException in case of the uid or name arguments are null
	 */
	function __construct($uid, $name, $pic_url = NULL) {
		if (empty($uid) || empty($name)) {
			throw new InvalidArgumentException("uid and name must be not null! (uid=$uid, name=$name)");
		}
		$this->fb_uid = $uid;
		$this->fb_name = $name;
		$this->fb_pic_url = $pic_url;
		$this->fb_location = null;
		$this->fb_friends = array();
	}

	///////////////////////////////////////////////////////////////////////////
	// FB uid
	//

	/**
	 * Returns the users FB uid.
	 * @return string not null
	 */
	public function getUid() {
		return $this->fb_uid;
	}

	///////////////////////////////////////////////////////////////////////////
	// FB full name
	//

	/**
	 * Returns the user FB full name
	 * @return string not null
	 */
	public function getName() {
		return $this->fb_name;
	}


	///////////////////////////////////////////////////////////////////////////
	// FB Profile Photo URL
	//

	/**
	 * Returns URL to the FB profile photo. If the user doesn't have one, then DEFAULT_PROFILE_PHOTO_URL if returned.
	 * @return string never null
	 */
	public function getProfilePhotoURL() {
		if (empty($this->fb_pic_url)) {
			return DEFAULT_PROFILE_PHOTO_URL;
		}
		 
		return $this->fb_pic_url;
	}


	///////////////////////////////////////////////////////////////////////////
	// Friends using this application
	//

	/**
	 * Note: Only those friends are considered who are also using this application!
	 * @return array of User objects (each is represention of one friend using this application),
	 * never null, if none of the friends is using this application then empty array.
	 */
	public function getFriends() {
		return $this->fb_friends;
	}

	/**
	 * Set the friends list - replaces the old one if exists - and sorts it according to location update time
	 * @param array $friendArray
	 */
	public function setFriends($friendArray) {
		if (isset($friendArray) && is_array($friendArray)) {
			$this->fb_friends = $friendArray;
			$this->sortFriends();
		}
		else {
			$this->fb_friends = array();
		}
	}

	/**
	 * Sorts the array of friends accroding to timestamp when their position was updated.
	 * The friends without specified location will be at the end of the list.
	 *
	 * @return
	 */
	public function sortFriends() {
		if (!isset($this->fb_friends) || !is_array($this->fb_friends)) {
			return;
		}

		// array of uid=timestamp pairs
		$timeArray = array();
		foreach ($this->fb_friends as $uid => $userObj) {
			$timeArray[$uid] = isset($userObj->fb_location) ? $userObj->fb_location->timestamp : 0;
		}
		// sort the array according to timestamp in reverse order, so the 1st will be the largest number
		arsort($timeArray, SORT_NUMERIC);

		// replave the timestamp value with the respective User object
		foreach ($timeArray as $uid => $time) {
			$timeArray[$uid] = $this->fb_friends[$uid];
		}

		$this->fb_friends = $timeArray;
	}

	///////////////////////////////////////////////////////////////////////////
	// Location
	//

	/**
	 * Sets the user location.
	 *
	 * @param $location Location
	 * @return unknown_type is the argument $location is not of type Location
	 */
	public function setLocation($location) {
		if (!($location instanceof Location)) {
			$this->fb_location = null;
			throw new InvalidArgumentException("Argument must be type of Location! ($location)");
		}
		 
		$this->fb_location = $location;
	}

	/**
	 * Returns the user's location
	 * @return Location
	 */
	public function getLocation() {
		return $this->fb_location;
	}

	///////////////////////////////////////////////////////////////////////////
    // Extra data
    //

	public function getExtraData($key) {
		return $this->fb_extra_data[$key];
	}
	
	public function setExtraDataValue($key, $value) {
		$this->fb_extra_data[$key] = $value;
	}
	
	/**
	 * Replaces the current fb_extra_data with the passed one.
	 * @param array $extraDataArray associative array of key-value pairs
	 */
    public function setExtraData($extraDataArray=array()) {
        $this->fb_extra_data = $extraDataArray;
    }
	///////////////////////////////////////////////////////////////////////////
	// toString
	//

	/**
	 * Returns the string representation of the User object.
	 *
	 * @param $show_friends whether to include in the string representation the list of friends.
	 * @return string
	 */
	public function toString($show_friends=FALSE) {
		$str = 'User: uid=' . $this->fb_uid . ', name=' . $this->fb_name . ', pic=' . $this->fb_pic_url;
		if (isset($this->fb_location)) {
			$str .= ', Location: (' . $this->fb_location->toString() . ')';
		}
		if ($show_friends && isset($this->fb_friends)) {
			$str .= "\n" . 'Friends:';
			foreach ($this->fb_friends as $key => $value) {
				$str .= "\n" . 'Friend:' . $value->toString();
			}
		}

		return $str;
	}
}

?>